﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using ZeroSum.DependencyInjection.Attributes;
using ZeroSum.Exceptions;
using ZeroSum.Extensions;
using ZeroSum.Plugin.Authentication.JwtBearer.Authorization;

namespace ZeroSum.Plugin.Authentication.JwtBearer.Authentication;

/// <summary>
///     权限授权处理器
/// </summary>
[Register(ServiceLifetime.Scoped)]
public class ZeroSumPermissionHandler : AuthorizationHandler<ZeroSumPermissionRequirement>
{
    private readonly IZeroSumAuthorization _authorization;
    private readonly IJwtBearerService _jwtBearerService;

    public ZeroSumPermissionHandler(IAuthenticationSchemeProvider schemes, IZeroSumAuthorization authorization,
        IJwtBearerService jwtBearerService)
    {
        Schemes = schemes;
        _authorization = authorization;
        _jwtBearerService = jwtBearerService;
    }

    /// <summary>
    ///     验证方案提供对象
    /// </summary>
    private IAuthenticationSchemeProvider Schemes { get; }


    public override async Task HandleAsync(AuthorizationHandlerContext context)
    {
        if (_jwtBearerService.AutoRefreshToken(context, context.GetCurrentHttpContext()))
            await base.HandleAsync(context);
        else
            context.Fail(); // 授权失败
        //var currentHttpContext = context.GetCurrentHttpContext();
        //currentHttpContext.SignoutToSwagger();
    }

    /// <summary>
    ///     如果根据特定要求允许授权，则作出决定。
    /// </summary>
    /// <param name="context">The authorization context.</param>
    /// <param name="requirement">The requirement to evaluate.</param>
    protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
        ZeroSumPermissionRequirement requirement)
    {
        var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
        if (context.Resource is HttpContext httpContext)
        {
            var authenticateResult = await httpContext.AuthenticateAsync(defaultAuthenticate?.Name);
            var principal = authenticateResult.Principal;

            //未登录
            if (principal is not {Identity: {IsAuthenticated: true}})
                throw NeedLoginException.Of("该操作需要登录后才能继续进行");

            // 管理员跳过判断
            var userId = httpContext.User.Identity.GetUserId()!.Value;
            var isSuperAdmin = await _authorization.IsSuperAdmin(userId);
            if (isSuperAdmin)
            {
                context.Succeed(requirement);
                return;
            }

            // 路由名称
            var permission = httpContext.Request.Path.Value?.Substring(1).Replace("/", ":").ToLower();

            var checkForPermission = await _authorization.CheckForPermission(userId, permission);

            // 检查授权
            if (checkForPermission)
                context.Succeed(requirement);
            else
                throw UnAuthorizeException.Of("该操作需要权限才能继续进行");
        }
        else
        {
            throw NeedLoginException.Of("该操作需要登录后才能继续进行");
        }
    }
}